using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;

namespace RPGOnline.Remoting.Entities
{
    [DataContract]
    public class SessionContext
    {
        [DataMember]
        private Dictionary<Guid, ChatGroup> m_groups = new Dictionary<Guid, ChatGroup>();

        public IEnumerable<ChatGroup> Groups { get { return m_groups.Values; } }
        public ChatGroup MainChatGroup { get { return m_groups[Guid.Empty]; } }
        public User MasterUser { get; set; }

        public SessionContext()
        {
            m_groups[Guid.Empty] = new ChatGroup("Main Chat", Guid.Empty);
        }

        public void AddGroup(ChatGroup group)
        {
            m_groups.Add(group.Id, group);
        }

        public void RemoveGroup(Guid groupId)
        {
            m_groups.Remove(groupId);
        }

        public void AddUser(User user, ChatGroup chatGroup)
        {
            chatGroup.Add(user);
        }

        public ChatGroup FindGroupById(Guid groupId)
        {
            ChatGroup chatGroup;
            if (!m_groups.TryGetValue(groupId, out chatGroup))
                return null;
            return chatGroup;
        }

        public bool GroupExists(Guid groupId)
        {
            return m_groups.ContainsKey(groupId);
        }

        public ChatGroup FindChatGroupByName(string groupName)
        {
            return Groups.FirstOrDefault(g => g.Name.Equals(groupName, StringComparison.InvariantCultureIgnoreCase));
        }

        public void Update(SessionContext sessionContext)
        {
            m_groups = sessionContext.m_groups;
        }

        public bool UserExists(User user)
        {
            return Groups.FirstOrDefault(g => g.Contains(user.Id)) != null;
        }

        public void RemoveUser(User user)
        {
            ChatGroup chatGroup = Groups.FirstOrDefault(g => g.Contains(user.Id));
            if (chatGroup == null)
                return;

            chatGroup.Remove(user);
        }

        public ChatGroup FindGroupByUser(User user)
        {
            return m_groups.Values.FirstOrDefault(g => g.Contains(user.Id));
        }

        public bool UserIsInGroup(User user, Guid chatGroupId)
        {
            return FindGroupById(chatGroupId).Contains(user.Id);
        }

        public bool UserIsMaster(User user)
        {
            return MasterUser.Equals(user);
        }

        public bool CanUserSendMessageToGroup(User user, Guid chatGroupId)
        {
            return UserIsInGroup(user, chatGroupId) || UserIsMaster(user) || MainChatGroup.Id == chatGroupId;
        }

        public User FindUserByName(string userName)
        {
            ChatGroup chatGroup = m_groups.Values.FirstOrDefault(g => g.Contains(userName));
            if (chatGroup == null)
                return null;
            return chatGroup.FindUserByName(userName);
        }

        public User FindByCharacterName(string characterName)
        {
            ChatGroup chatGroup = m_groups.Values.FirstOrDefault(u => u.FindByCharacterName(characterName) != null);
            if (chatGroup == null)
                return null;
            return chatGroup.FindByCharacterName(characterName);
        }
    }
}